﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Configurations.Controller;

namespace Pixysoft.Framework.Configurations.Core
{
    class HtmlNode : IHtmlNode
    {
        string parentPath;

        int nestLevel = 0;

        int nodeIndex = 0;


        string elementName = null;

        string text;

        string rawAttribute = null;

        List<IHtmlNode> list = new List<IHtmlNode>();

        public HtmlNode(string elementName, string rawAttribute, string parentPath, int nestLevel, int nodeIndex)
        {
            this.elementName = elementName;

            this.rawAttribute = rawAttribute;

            this.parentPath = parentPath;

            this.nestLevel = nestLevel;

            this.nodeIndex = nodeIndex;
        }

        public string ElementName
        {
            get { return elementName; }
            set { elementName = value; }
        }

        public string Text
        {
            get { return text; }
            set { text = value; }
        }

        public string RawAttribute
        {
            get { return rawAttribute; }
            set { rawAttribute = value; }
        }

        public IHtmlNodeCollection Node
        {
            get
            {
                return new HtmlNodeCollection(list, parentPath + nodeIndex + StringHelper.default_html_pathspliter, nestLevel + 1);
            }
        }

        public IHtmlNodesCollection Nodes
        {
            get
            {
                return new HtmlNodesCollection(list, parentPath + nodeIndex + StringHelper.default_html_pathspliter, nestLevel + 1);
            }
        }

        public string HtmlId
        {
            get
            {
                if (string.IsNullOrEmpty(rawAttribute))
                    return null;

                string htmltag = string.Format("<{0} {1} />", elementName, rawAttribute);

                try
                {
                    return XmlNodeController.Instance.DeserializeToNode(htmltag).Properties["id"];
                }
                catch
                {
                    return null;
                }
            }
        }

        public string HtmlClass
        {
            get
            {
                if (string.IsNullOrEmpty(rawAttribute))
                    return null;

                string htmltag = string.Format("<{0} {1} />", elementName, rawAttribute);

                try
                {
                    return XmlNodeController.Instance.DeserializeToNode(htmltag).Properties["class"];
                }
                catch
                {
                    return null;
                }
            }
        }


        public bool IsEmpty
        {
            get
            {
                if (!string.IsNullOrEmpty(text))
                    return false;

                if (list.Count > 0)
                    return false;

                return true;
            }
        }

        public bool IsWellFormatted
        {
            get { return true; }
        }

        public string ParentPath
        {
            get { return parentPath; }
            set { parentPath = value; }
        }

        public int NestLevel
        {
            get { return nestLevel; }
            set { nestLevel = value; }
        }

        public int NodeIndex
        {
            get { return nodeIndex; }
            set { nodeIndex = value; }
        }


        public string GetPlainNodeBody()
        {
            return HtmlController.Instance.TransferToPlainContent(this.Serialize());
        }


        public string Serialize()
        {
            StringBuilder attributestr = new StringBuilder();

            attributestr.Append(elementName);

            if (attributestr.Length > 0 && !string.IsNullOrEmpty(rawAttribute))
                attributestr.Append(" ");

            attributestr.Append(rawAttribute);

            if (IsEmpty)
            {
                return string.Format("<{0}/>", attributestr.ToString());
            }
            else
            {
                StringBuilder builder = new StringBuilder();

                builder.Append(string.Format("<{0}>", attributestr.ToString()));

                if (!string.IsNullOrEmpty(text))
                    builder.Append(text);

                if (list.Count > 0)
                {
                    foreach (IHtmlNode child in list)
                    {
                        builder.Append(child.Serialize());
                    }
                }

                builder.Append(string.Format("</{0}>", elementName));

                return builder.ToString();
            }
        }

        public string Serialize(bool indent)
        {
            StringBuilder attributestr = new StringBuilder();

            attributestr.Append(elementName);

            if (attributestr.Length > 0 && !string.IsNullOrEmpty(rawAttribute))
                attributestr.Append(" ");

            attributestr.Append(rawAttribute);

            if (IsEmpty)
            {
                return string.Format("<{0}/>", attributestr.ToString());
            }
            else
            {
                FormatStringBuilder builder = new FormatStringBuilder();

                builder.AppendLine("<{0}>", attributestr.ToString());

                builder.Indent();

                if (!string.IsNullOrEmpty(text))
                    builder.AppendLine(text);

                if (list.Count > 0)
                {
                    foreach (IHtmlNode child in list)
                    {
                        foreach (string line in child.Serialize(indent).Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            builder.AppendLine(line);
                        }
                    }
                }

                builder.Outdent();

                builder.AppendLine("</{0}>", elementName);

                return builder.ToString();
            }
        }

        public string SerializeToLayout()
        {
            StringBuilder attributestr = new StringBuilder();

            attributestr.Append(string.Format("node path='{0}' element='{1}' ", parentPath + nodeIndex, elementName));
            attributestr.Append(rawAttribute);

            if (IsEmpty)
            {
                return string.Format("<{0}/>", attributestr.ToString());
            }
            else
            {
                FormatStringBuilder builder = new FormatStringBuilder();

                builder.AppendLine("<{0}>", attributestr.ToString());

                builder.Indent();

                if (!string.IsNullOrEmpty(text))
                    builder.AppendLine(text);

                if (list.Count > 0)
                {
                    foreach (IHtmlNode child in list)
                    {
                        foreach (string line in child.SerializeToLayout().Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            builder.AppendLine(line);
                        }
                    }
                }

                builder.Outdent();

                builder.AppendLine("</node>");

                return builder.ToString();
            }
        }

        public override string ToString()
        {
            return string.Format("<{0} {1}>", elementName, rawAttribute);
        }

    }
}
